package com.example.haxballandroid;


//TO BE CLEANED UP
import gamemodel.GoalPost;
import gamemodel.Playground;
import gamemodel.ScoreBoard;

import java.util.ArrayList;
import java.util.HashMap;					
import java.util.LinkedList;

import org.andengine.engine.camera.BoundCamera;
//import org.andengine.engine.camera.Camera;
import org.andengine.engine.camera.hud.HUD;
import org.andengine.engine.camera.hud.controls.AnalogOnScreenControl;
import org.andengine.engine.camera.hud.controls.AnalogOnScreenControl.IAnalogOnScreenControlListener;
import org.andengine.engine.camera.hud.controls.BaseOnScreenControl;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.modifier.ScaleModifier;
import org.andengine.entity.modifier.SequenceEntityModifier;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.scene.background.SpriteBackground;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.util.FPSLogger;
import org.andengine.input.touch.TouchEvent;
import org.andengine.input.touch.controller.MultiTouch;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.ui.activity.SimpleBaseGameActivity;

import phone.beans.BallBean;
import phone.beans.GameServerBean;
import phone.beans.PlayerBean;
import phone.beans.ScoreBoardBean;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.opengl.GLES20;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;


/**
 * (c) 2010 Nicolas Gramlich
 * (c) 2011 Zynga
 *
 * @author Nicolas Gramlich
 * @since 00:06:23 - 11.07.2010
 * Modified by: Shahin Kahriz - 2012
 */
public class GameFieldActivity extends SimpleBaseGameActivity {

	/** To be modified to match model **/
	private static final int CAMERA_WIDTH = 500;
	private static final int CAMERA_HEIGHT = 320;
	private static final float GOALPOST_MAX_X = 800; 
	private static final float GOALPOST_MAX_Y = 270; 
	private static final float GOALPOST_MIN_X = 0; 
	private static final float GOALPOST_MIN_Y = 130; 
	private static final int MAX_PLAYERS = 4;
	
	private BoundCamera mCamera;
	private BitmapTextureAtlas mBitmapTextureAtlas, mBallTexture, mGoalPostTexture, mFieldTexture, mBlueTexture;
	private BitmapTextureAtlas mOnScreenButtonTexture;	
	private ITextureRegion mFaceTextureRegion, mOnScreenShootButton, mBall, mPost, mField, mBlueFace;
	private BitmapTextureAtlas mOnScreenControlTexture;
	private ITextureRegion mOnScreenControlBaseTextureRegion;
	private ITextureRegion mOnScreenControlKnobTextureRegion;
	public final static String MESSAGE_TAG = "com.example.haxballandroid.MESSAGE";
	private Intent intent, intentServ;
	private Sprite shootButton, ball, field;		//TO BE TRANSFERRED TO players HASHMAP

	private Sprite goalPostOne, goalPostTwo, goalPostThree, goalPostFour;
	private String username, currPlayer;
	final Scene scene = new Scene();
	
	private ArrayList<Sprite> players;
	private HashMap<String, Integer> playerList;
	private HashMap<String, Integer> playerTeam;
	private int playerID;

	
	private ArrayList<Sprite> teamA, teamB;
	
	
	
	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		intent = new Intent(this, ActionUpdate.class);
		players = new ArrayList<Sprite>(MAX_PLAYERS);
		playerList = new HashMap<String, Integer>();
		playerTeam = new HashMap<String, Integer>();
		if(ActionUpdate.username != null)
			this.username = ActionUpdate.username;
		playerID = 0;

	
	}
	
	@Override
	public EngineOptions onCreateEngineOptions() {
		this.mCamera = new BoundCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);		//bound camera needed to lose focus from sprite at map borders
		mCamera.setBounds(0,0,800,400);		//TODO no hardcoding
		mCamera.setBoundsEnabled(true);
		final EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera);
		engineOptions.getTouchOptions().setNeedsMultiTouch(true);

		if(MultiTouch.isSupported(this)) {
			if(MultiTouch.isSupportedDistinct(this)) {
				Toast.makeText(this, "MultiTouch detected --> Both controls will work properly!", Toast.LENGTH_SHORT).show();
			}
		} else {
			Toast.makeText(this, "Sorry your device does NOT support MultiTouch!\n\n(Falling back to SingleTouch.)\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG).show();
		}

		return engineOptions;
	}

	@Override
	public void onCreateResources() {
		BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

		
		this.mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "face_circle_tiled.png", 0, 0);
		this.mBitmapTextureAtlas.load();
		
		this.mBlueTexture = new BitmapTextureAtlas(this.getTextureManager(), 32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mBlueFace = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBlueTexture, this, "faceBlue.png", 0, 0);
		this.mBlueTexture.load();
		
		this.mGoalPostTexture = new BitmapTextureAtlas(this.getTextureManager(), 30, 30, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mPost = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mGoalPostTexture, this, "goalpost.png", 0, 0);
		this.mGoalPostTexture.load();
		

		this.mOnScreenControlTexture = new BitmapTextureAtlas(this.getTextureManager(), 256, 128, TextureOptions.BILINEAR);
		this.mOnScreenControlBaseTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "onscreen_control_base.png", 0, 0);
		this.mOnScreenControlKnobTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "onscreen_control_knob.png", 128, 0);
		this.mOnScreenControlTexture.load();

		this.mOnScreenButtonTexture = new BitmapTextureAtlas(this.getTextureManager(), 100, 100, TextureOptions.BILINEAR);
		this.mOnScreenShootButton = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenButtonTexture, this, "onscreen_shoot_button.png", 0, 0);
		this.mOnScreenButtonTexture.load();
		
		this.mBallTexture = new BitmapTextureAtlas(this.getTextureManager(), 26, 26, TextureOptions.BILINEAR);
		this.mBall = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBallTexture, this, "ball.png", 0, 0);
		this.mBallTexture.load(); 
		
		this.mFieldTexture = new BitmapTextureAtlas(this.getTextureManager(), 815, 408, TextureOptions.BILINEAR);
		this.mField = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mFieldTexture, this, "field.png", 0, 0);
		this.mFieldTexture.load();
		
		
	}

	@Override
	public Scene onCreateScene() {
		init();
		scene.attachChild(new Sprite(1, 1, this.mField, this.getVertexBufferObjectManager()));
		
		this.mEngine.registerUpdateHandler(new FPSLogger());
		HUD mHUD = new HUD();									//HUD for the shoot button

		final float centerX = (CAMERA_WIDTH - this.mFaceTextureRegion.getWidth()) / 2;
		final float centerY = (CAMERA_HEIGHT - this.mFaceTextureRegion.getHeight()) / 2;
		
		for(int i = 0; i < MAX_PLAYERS; i++)
				players.add(new Sprite(centerX, centerY, this.mFaceTextureRegion, this.getVertexBufferObjectManager()));
	
		for(String key : playerTeam.keySet()){
			if(playerTeam.get(key) != 0)
				players.set(playerList.get(key), new Sprite(centerX, centerY, this.mBlueFace, this.getVertexBufferObjectManager()));
		}
		
		
		this.mCamera.setChaseEntity(players.get(playerID));

		
		ball = new Sprite(centerX+50, centerY+90, this.mBall, this.getVertexBufferObjectManager());
		
		shootButton = new Sprite(CAMERA_WIDTH - this.mOnScreenShootButton.getWidth(), CAMERA_HEIGHT - this.mOnScreenShootButton.getHeight(), this.mOnScreenShootButton, this.getVertexBufferObjectManager()){
			@Override
			public boolean onAreaTouched(TouchEvent pEvent, float pX, float pY){
				if(pEvent.isActionDown()){
					sendUpdate("kick");				//TODO no hardcoding 
					shootButton.setAlpha(1.0f);					//alpha layer transparency, 1 when button is pressed
					players.get(playerID).registerEntityModifier(new SequenceEntityModifier(new ScaleModifier(0.25f, 1, 1.5f), new ScaleModifier(0.25f, 1.5f, 1)));
				}
				else{
					shootButton.setAlpha(0.50f);				//alpha layer transparency, transparent otherwise
					return false;
				}
				return mFlippedHorizontal;
			}
		};
		shootButton.setAlpha(0.50f);		//default must be transparent
		

		
		//final PhysicsHandler physicsHandler = new PhysicsHandler(playerOne);
		//playerOne.registerUpdateHandler(physicsHandler);
		for(String key : playerList.keySet())
			scene.attachChild(players.get(playerList.get(key)));
		
		scene.attachChild(ball);
		this.mCamera.setHUD(mHUD);
		mHUD.attachChild(shootButton);
		mHUD.registerTouchArea(shootButton);
		
		
		final AnalogOnScreenControl analogOnScreenControl = new AnalogOnScreenControl(0, CAMERA_HEIGHT - this.mOnScreenControlBaseTextureRegion.getHeight(), this.mCamera, this.mOnScreenControlBaseTextureRegion, this.mOnScreenControlKnobTextureRegion, 0.1f, 200, this.getVertexBufferObjectManager(), new IAnalogOnScreenControlListener() {
			
			@Override
			public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
				//physicsHandler.setVelocity(pValueX * 100, pValueY * 100);
				if(pValueX != 0 || pValueY != 0)
					sendUpdate(pValueX, pValueY);
				else
					sendUpdate(0,0);
			}

			@Override
			public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {

			}	
		});
		
		analogOnScreenControl.getControlBase().setBlendFunction(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
		analogOnScreenControl.getControlBase().setAlpha(0.5f);
		analogOnScreenControl.getControlBase().setScaleCenter(0, 128);
		analogOnScreenControl.getControlBase().setScale(1.25f);
		analogOnScreenControl.getControlKnob().setScale(1.25f);
		analogOnScreenControl.refreshControlKnobPosition();

		scene.setChildScene(analogOnScreenControl);

		return scene;
	}
	
	/**
	 * Receives updates from the service and makes a call to updateUI to update the game state.
	 */
	public BroadcastReceiver broadcastReceiver = new BroadcastReceiver(){
		@Override
		public void onReceive(Context context, Intent updateIntent){
			updateUI(updateIntent);
		}

	};
	
	@Override
	public void onResume(){
		super.onResume();
		startService(intent);
		registerReceiver(broadcastReceiver, new IntentFilter(ActionUpdate.BROADCAST_ACTION));
	}
	
	@Override
	public void onPause(){
		super.onPause();
		unregisterReceiver(broadcastReceiver);
		//stopService(intent);
	}
	
	
	public void init(){
		goalPostOne = new Sprite(GOALPOST_MIN_X, GOALPOST_MIN_Y, this.mPost, this.getVertexBufferObjectManager());
		goalPostTwo = new Sprite(GOALPOST_MIN_X, GOALPOST_MAX_Y, this.mPost, this.getVertexBufferObjectManager());	
		goalPostThree = new Sprite(GOALPOST_MAX_X, GOALPOST_MIN_Y, this.mPost, this.getVertexBufferObjectManager());	
		goalPostFour = new Sprite(GOALPOST_MAX_X, GOALPOST_MAX_Y, this.mPost, this.getVertexBufferObjectManager());	
		scene.attachChild(goalPostOne);
		scene.attachChild(goalPostTwo);
		scene.attachChild(goalPostThree);
		scene.attachChild(goalPostFour);
		
		GameServerBean bean	= ActionUpdate.updateBean;
		HashMap<String, PlayerBean> temp = new HashMap<String, PlayerBean>();
		temp = bean.getGameModel().getPlayerList();
		
		int counter = 0;
		for(String key : temp.keySet()){
			playerList.put(key, counter);
			playerTeam.put(key, temp.get(key).getTeam());
			if(key.equals(username)){
				playerID = counter;
			}
			counter++;
		}
			
		
		
	}
	
	/**
	 * Will parse the incoming intent and update the UI accordingly
	 * @param intent
	 */
	private void updateUI(Intent updateIntent){
		try{		//TODO REMOVE code smell
			//TODO major cleanup after player numbers are sent in	
			GameServerBean bean	= ActionUpdate.updateBean;
			//Retrieve the values placed in the intent in the ActionUpdate service using a Bundle
			
			//will be changed later - will be passing coordinate object instead of moves	
			HashMap<String, PlayerBean> temp = new HashMap<String, PlayerBean>();
			
			temp = bean.getGameModel().getPlayerList();
			
			for(String key : playerList.keySet()){
				PlayerBean b = temp.get(key);
				players.get(playerList.get(key)).setPosition(b.getPosition().getX(), b.getPosition().getY());
			}
			ScoreBoardBean sBean = bean.getGameModel().getScoreboard();
			BallBean bBall = bean.getGameModel().getBall();
			ball.setPosition(bBall.getPosition().getX(), bBall.getPosition().getY());
			
		}
		catch(NullPointerException e){
			
		}
	}
	
	
	public void sendUpdate(String kick){
		intentServ = new Intent(this, ActionUpdate.class);
		intentServ.putExtra(MESSAGE_TAG, "kick");
		startService(intentServ);
	}	
	
	public void sendUpdate(float x, float y){
		intentServ = new Intent(this, ActionUpdate.class);
		intentServ.putExtra(MESSAGE_TAG, "move");
		intentServ.putExtra("X", x);
		intentServ.putExtra("Y", y);
		startService(intentServ);
	}	

}//end Activity
